package com.mobilottery.ui;

import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.regex.Pattern;

import com.mobilottery.server.GameProvider;

/**
 * Base class for form backing beans, provides common validation routines
 * @author fedor
 */
public abstract class ValidationForm 
{
	//default date format representation
    public static final SimpleDateFormat DATE_FORMAT = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
    public static final DecimalFormat PRICE_FORMAT =  new DecimalFormat("#.##");    
    //validation errors by field
	private Map<String, String> errors = new HashMap<String, String>();
	
	/**
	 * Associates an error message with the field
	 * @param fieldName
	 * @param errorMessage
	 */
	public void setFieldErorrMessage(String fieldName, String errorMessage)
	{
		errors.put(fieldName, errorMessage);
	}
	
	/**
	 * Returns an error message associated with the field or empty string otherwise
	 * @param fieldName
	 * @return
	 */
	public String getFieldErorrMesssage(String fieldName)
	{
		String fieldError =  errors.get(fieldName);
		return fieldError!=null ? fieldError : "";
	}
	
	
	final static Pattern USERNAME_PATTERN = Pattern.compile("[a-zA-Z0-9]*");
	final static Pattern NAME_PATTERN = Pattern.compile("[a-zA-Z]*");
	final static Pattern MAIL_PATTERN = Pattern.compile(".+@.+\\.[a-z]+");
	
	protected boolean validateName(String field, String value)
	{
		if(value.length()<4 || !NAME_PATTERN.matcher(value).matches())
		{
			final String nameError = "Invalid name '" + value + "', must contain at least four characters (latin letters only)";
			setFieldErorrMessage(field, nameError);
			return false;
		}		
		return true;
	}
	
	protected boolean validateUserName(String field, String value)
	{
		if(value.length()<4 || !USERNAME_PATTERN.matcher(value).matches())
		{
			final String nameError = "Invalid username '" + value + "', must contain at least four alphanumeric characters";
			setFieldErorrMessage(field, nameError);
			return false;
		}		
		return true;
	}	

	protected boolean validateCreditCard(String field, String value)
	{
		String validationResult = GameProvider.getInstance().getLotterySystem().checkCreditCard(value);
		if(validationResult.length()>0)
		{
			setFieldErorrMessage(field, validationResult);
			return false;
		}
		return true;
	}
	
	protected boolean validateMail(String field, String value)
	{
		if(!MAIL_PATTERN.matcher(value).matches())
		{
			final String mailError = "Invalid e-mail address, must be in the form abc@xyz.tld";
			setFieldErorrMessage(field, mailError);
			return false;
		}				
		return true;		
	}
	
	protected boolean validatePassword(String field, String value)
	{
		if(value.length()<4)
		{
			final String passwordError = "Password is too short, must contain at least 4 characters";
			setFieldErorrMessage(field, passwordError);
			return false;
		}				
		return true;		
	}
	
	
	protected Date parseDate(String fieldName, String value, Date defaultDate)
	{
		try
		{
			return value!=null ? DATE_FORMAT.parse(value) : null;
		}
		catch(Exception ex)
		{
			setFieldErorrMessage(fieldName, value  + " date is invalid, expected format: " + DATE_FORMAT.toPattern());			
		}
		return defaultDate;
	}
	
	
	protected float parseNumber(String fieldName, String value, float defaultValue)
	{
		try
		{
			return Float.parseFloat(value);
		}
		catch(Exception ex)
		{
			setFieldErorrMessage(fieldName, value + " is not numeric value");
		}
		return defaultValue;
	}	
	
	protected boolean checkNonEmpty(String fieldName, Object value)
	{
		if(value==null || value.toString().length()==0)
		{
			setFieldErorrMessage(fieldName, "value is mandatory");
			return false;
		}
		return true;
	}
	
	
	protected boolean checkDatePast(String fieldName, Date value, Date pastDate)
	{
		if(pastDate!=null && value.getTime() < pastDate.getTime())
		{
			setFieldErorrMessage(fieldName, "date must be after " + DATE_FORMAT.format(pastDate));
			return false;
		}
		return true;
	}	
		
	public boolean hasErrors()
	{
		return !errors.isEmpty();
	}
		
	public boolean isSubmitted()
	{
		return !hasErrors();
	}	
	
	public void reset()
	{
		errors.clear();
	}
	
	public abstract void submit();
	
	
}
